package com.chao.wind3j.base.config.commonConfig.requestLogConfig.requestFunctionAop;

import com.alibaba.fastjson.JSON;
import com.chao.wind3j.base.config.commonConfig.CommonProperties;
import com.chao.wind3j.base.config.commonConfig.requestLogConfig.requestWrapper.CustomRequestWrapper;
import com.chao.wind3j.model.dataBaseModel.Wind3Request;
import com.chao.wind3j.service.Wind3RequestService;
import com.chao.wind3j.util.DateFormat;
import com.chao.wind3j.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.UUID;

@Slf4j
@Aspect
@Component
public class RequestLogConfig implements Ordered {

  @Autowired
  private Wind3RequestService wind3RequestService;

  @Autowired
  private CommonProperties commonProperties;

  @Around("commonController()")
  public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    return this.handle(joinPoint);
  }

  @Pointcut("execution(public * com.chao.wind3j.controller..*.*(..))")
  private void commonController () {
  }

  @Pointcut("@annotation(org.springframework.web.bind.annotation.ExceptionHandler))")
  private void exceptionController () {
  }

  public Object handle(ProceedingJoinPoint joinPoint) throws Throwable {
    var requestAttribute = RequestContextHolder.getRequestAttributes();
    assert requestAttribute != null;
    var wind3Request = new Wind3Request();
    var request = ((ServletRequestAttributes) requestAttribute).getRequest();
    if (request.getAttribute("requestId") == null) {
      request.setAttribute("requestId", UUID.randomUUID().toString());
      wind3Request.setRequestId(request.getAttribute("requestId").toString());
      this.handleRequestInfo(new CustomRequestWrapper(request, this.commonProperties), joinPoint, wind3Request);
    } else {
      wind3Request.setRequestId(request.getAttribute("requestId").toString());
    }
    var result = joinPoint.proceed();
    var response = ((ServletRequestAttributes) requestAttribute).getResponse();
    var updateWind3Request = new Wind3Request();
    updateWind3Request.setRequestId(wind3Request.getRequestId());
    updateWind3Request.setResponseContent(JSON.toJSONString(result));
    this.wind3RequestService.updateWind3Request(updateWind3Request);
    return result;
  }


  @Override
  public int getOrder() {
    return 0;
  }

  private void handleRequestInfo(CustomRequestWrapper requestWrapper, ProceedingJoinPoint joinPoint, Wind3Request wind3Request) {
    var requestInfo = requestWrapper.getRequestInfo();
    wind3Request.setRequestContent(JSON.toJSONString(requestInfo));
    wind3Request.setRequestDateTime(DateUtil.getDateFromFormat(requestInfo.getRequestTime(), DateFormat.format_yyyy_MM_dd_HH_mm_ss));
    wind3Request.setRequestMethodName(joinPoint.getSignature().getName());
    this.wind3RequestService.insertWind3Request(wind3Request);
    this.printRequestInfo(requestWrapper, joinPoint);
  }

  private void printRequestInfo(CustomRequestWrapper requestWrapper, ProceedingJoinPoint joinPoint) {
    System.out.println(requestWrapper.getRequestInfo());
  }

}
